package com.aioething.iot.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aioething.iot.service.IEmqxService;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Credentials;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.tio.utils.lock.MapWithLock;

import java.io.IOException;

@Service
@Slf4j
public class EmqxService implements IEmqxService {
    @Value("${emqx.api.url}")
    private String api;
    @Value("${emqx.api.apiKey}")
    private String apiKey;
    @Value("${emqx.api.secretKey}")
    private String secretKey;

    private MapWithLock<String, String> syncLock = new MapWithLock<>();

    public HttpResponse publish(String topic, String payload) throws IOException {
        return new HttpRequest(api.concat("publish")).method(Method.POST)
                .header("Authorization", Credentials.basic(apiKey, secretKey))
                .header("Content-Type", "application/json")
                .body(JSONUtil.createObj().set("topic", topic).set("payload", payload).toString()).execute();
    }

    public JSONObject actionCall(String topic, String method, String equipmentId, JSONObject params) throws IOException {
        String clientToken = IdUtil.fastSimpleUUID();
        String payload = JSONUtil.createObj().set("method", method).set("clientToken", clientToken).set("params", params).toString();
        HttpRequest request = new HttpRequest(api.concat("publish")).method(Method.POST)
                .header("Authorization", Credentials.basic(apiKey, secretKey))
                .header("Content-Type", "application/json")
                .body(JSONUtil.createObj().set("topic", topic).set("payload", payload).toString());
        String lockObj = new String();
        syncLock.put(clientToken, lockObj);
        synchronized (lockObj) {
            try {
                HttpResponse response = request.execute();
                if (response.getStatus() == HttpStatus.HTTP_OK) {
                    lockObj.wait(3000);
                }
            } catch (InterruptedException e) {
                log.error(e.getMessage());
            } finally {
                String resMsg = syncLock.remove(lockObj);
                if (lockObj.equals(resMsg)) {
                    throw new InternalException("终端响应超时");
                }
                return JSONUtil.parseObj(resMsg);
            }
        }
    }

    @Override
    public MapWithLock<String, String> getSyncLock() {
        return syncLock;
    }
}
